/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include <pgl/mfc/PGLDialogList.h>
#include <pgl/mfc/PGLMFCGlobal.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPGLDialogList::CPGLDialogList()
{
}

CPGLDialogList::~CPGLDialogList()
{
	RemoveAll();
}

void CPGLDialogList::AddHead(CPGLDialog* pGraphDlg)
{	
	PGL_TRACE(_T("PGL-GraphDlgList: Adding CPGLDialog to List of dialogs.\n"));
	if (!pGraphDlg)
		return;

	ASSERT_VALID(pGraphDlg);
	bool bCreated=true;
	CString str;

	CSingleLock synchro(&m_ThreadLock);
	synchro.Lock();
	if (synchro.IsLocked())
	{
		// creating if needed
		if (! pGraphDlg->GetSafeHwnd() )
		{
			// saving old ressource.
			HINSTANCE hOldInst=AfxGetResourceHandle();
			// setting dll ressource
			AfxSetResourceHandle(CPGLMFCGlobal::GetInstance());
			// creating dialog
			bCreated=pGraphDlg->Create(IDD_PGL_DIALOG_GRAPH);

			// restoring old ressource.
			AfxSetResourceHandle(hOldInst);
		}
	
		if (bCreated)
		{
			pGraphDlg->SetDialogManager(this);
			m_lPlots.push_front(pGraphDlg);
			pGraphDlg->ShowWindow(SW_SHOWNORMAL);   
		}
		else
		{
			pGraphDlg->GetWindowText(str);
			AfxMessageBox("Failed to create dialog box for graph "+str);
		}

		// release thread
		synchro.Unlock();
	}

	PGL_TRACE(_T("PGL-GraphDlgList: Graph added\n"));
}

void CPGLDialogList::ShowAll()
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
	{
		pGraphDlg=*ip;

		if (!pGraphDlg->GetSafeHwnd())
		{
			// saving old ressource.
			HINSTANCE hOldInst=AfxGetResourceHandle();
			// setting dll ressource
			AfxSetResourceHandle(CPGLMFCGlobal::GetInstance());
			// creating dialog
			pGraphDlg->Create(IDD_PGL_DIALOG_GRAPH);
			// restoring old ressource.
			AfxSetResourceHandle(hOldInst);
		}

		pGraphDlg->ShowWindow(SW_SHOWNORMAL);   
	}
	TRACE(_T("PGL-GraphDlgList: Graph Showed\n"));
}

void CPGLDialogList::Remove(CPGLDialog *_pGraphDlg)
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	if (_pGraphDlg==NULL)
		return;

	if (_pGraphDlg->IsWindowVisible())
		return;


	CSingleLock synchro(&m_ThreadLock);
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{

		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			if (pGraphDlg==_pGraphDlg)
			{
				// removing from list
				m_lPlots.erase(ip);
				pGraphDlg->DestroyWindow();
				delete pGraphDlg;
				pGraphDlg=NULL;

				// release thread
				synchro.Unlock();
				return;
			}
		}
		// release thread
		synchro.Unlock();
	}
}	
	
void CPGLDialogList::RemoveAll()
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	PGL_TRACE(_T("PGL-GraphDlgList::RemoveAll: Removing all graph dialogs\n"));
	if (m_lPlots.empty())
	{
		PGL_TRACE(_T("PGL-GraphDlgList::RemoveAll: Empty, nothing to do\n"));
		return;
	}

	CSingleLock synchro(&m_ThreadLock);
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			// cleaning graph
			if (pGraphDlg)
			{
				WINDOWPLACEMENT pwndpl;
				pwndpl.length=sizeof(WINDOWPLACEMENT);
				pwndpl.showCmd=SW_HIDE;
				VERIFY(pGraphDlg->SetWindowPlacement( &pwndpl));
				delete pGraphDlg;
				pGraphDlg=NULL;
			}
		}
		m_lPlots.clear();

		//release thread
		synchro.Unlock();
	}

	PGL_TRACE(_T("PGL-GraphDlgList: Graphs dialogs removed\n"));
}


void CPGLDialogList::RemoveHidden()
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	CSingleLock synchro(&m_ThreadLock);
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			ASSERT(pGraphDlg);
			if (! pGraphDlg->IsWindowVisible() )
			{
				VERIFY(pGraphDlg->DestroyWindow());
				delete pGraphDlg;

				// removing pointer
				m_lPlots.erase(ip);				
			}
		}

		// release thread
		synchro.Unlock();
	}
}

//! return number of visible dialog windows
UINT CPGLDialogList::GetVisibleSize()
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	CSingleLock synchro(&m_ThreadLock);
	UINT count = 0;
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			ASSERT(pGraphDlg);
			if (pGraphDlg->IsWindowVisible() )
			{
				count++;
			}
		}

		// release thread
		synchro.Unlock();

		return count;
	}
	else
		return 0;
}

//! return number of visible dialog windows
UINT CPGLDialogList::GetHiddenSize()
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	CSingleLock synchro(&m_ThreadLock);
	UINT count = 0;
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			ASSERT(pGraphDlg);
			if (!pGraphDlg->IsWindowVisible() )
			{
				count++;
			}
		}

		// release thread
		synchro.Unlock();

		return count;
	}
	else
		return 0;
}

//! return true if dialog is in list
bool CPGLDialogList::IsInList(CPGLDialog* _pGraphDlg)
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	CSingleLock synchro(&m_ThreadLock);
	UINT count = 0;
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			if ( _pGraphDlg == pGraphDlg)
			{
				synchro.Unlock();
				return true;
			}
		}

		// release thread
		synchro.Unlock();
	}

	return false;
}

CPGLDialog* CPGLDialogList::Find( DWORD dwID)
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	CSingleLock synchro(&m_ThreadLock);
	UINT count = 0;
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			ASSERT(pGraphDlg);
			if ( pGraphDlg->IsID(dwID))
			{
				synchro.Unlock();
				return pGraphDlg;
			}
		}

		// release thread
		synchro.Unlock();
	}

	return NULL;
}

CPGLDialog* CPGLDialogList::FindFromRegion( DWORD dwRegionID)
{
	CPGLDialog* pGraphDlg;
	std::list<CPGLDialog*>::iterator ip;

	// getting region ID
	CPGLRegionStPtr pRegion=CPGLRegionPoolSingleton::Find( dwRegionID);
	if (!pRegion)
		return NULL;

	// get top region
	while(pRegion && pRegion->GetParent())
		pRegion=pRegion->GetParent();

	CSingleLock synchro(&m_ThreadLock);
	UINT count = 0;
	// locking thread
	synchro.Lock();
	if (synchro.IsLocked())
	{
		for (ip = m_lPlots.begin(); ip != m_lPlots.end(); ip++)
		{
			pGraphDlg=*ip;
			ASSERT(pGraphDlg);
			// get top region
			CPGLRegionPtr pDlgRegion=pGraphDlg->GetRegion();
			if ( pDlgRegion && (pDlgRegion->CheckID(pRegion->GetID())) )
			{
				synchro.Unlock();
				return pGraphDlg;
			}
		}

		// release thread
		synchro.Unlock();
	}

	return NULL;
}

CPGLDialog* CPGLDialogList::Create( CPGLRegionPtr pRegion )
{
	CPGLDialog* pDlg = new CPGLDialog(NULL, pRegion);
	if (!pDlg)
		return NULL;

	AddHead(pDlg);
	return pDlg;
};
